﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Xml;
using System.Globalization;
using EnvDTE;
using System.Reflection;
using System.Drawing.Design;
using System.Collections;

namespace SPVisualDev.VSAddin.Dialogs.PropertySheets
{
    internal class PropSheetListTemplate : PropSheetBase
    {
        public PropSheetListTemplate(string DefaultResourceFile, EnvDTE.ProjectItem ParentFeatureFolder, ElementInfo Element)
        {

            this.DefaultResourceFile = DefaultResourceFile;
            this.ParentFeatureFolder = ParentFeatureFolder;

            this.DisplayName = new ResourceStringContainer(string.Empty, DefaultResourceFile, ParentFeatureFolder);
            this.Description = new ResourceStringContainer(string.Empty, DefaultResourceFile, ParentFeatureFolder);


            this.ElementInfo = Element;

            this.ElementFileName = Element.ElementFileName;
            this.EventRegistrations = Element.EventReceivers;
            this.EventReceiverClasses = Element.AttachedEventReceiverClasses;

            if (Element.XmlElementNode != null)
                this.PropXmlNode = Element.XmlElementNode;

        }

        private BaseTypeInfoStruct m_original_type;
        [CategoryAttribute("NewTemplate"), Browsable(true), DisplayName("Built-in template to start from"), DescriptionAttribute("Original type"), ReadOnly(false), TypeConverter(typeof(OriginalTypeExpandableConverter))]
        public BaseTypeInfoStruct OriginalType
        {
            get
            {
                return m_original_type;
            }
            set
            {
                m_original_type = value;

                this.BaseType = m_original_type.BaseType;
            }
        }

        [CategoryAttribute("Properties"), DescriptionAttribute("Internal name"), RefreshProperties(RefreshProperties.None)]
        public string Name
        {
            get;
            set;
        }

        [CategoryAttribute("Properties"), DescriptionAttribute("Display name"), RefreshProperties(RefreshProperties.None), TypeConverter(typeof(ResourceExpandableObjectConverter))]
        public ResourceStringContainer DisplayName
        {
            get;
            set;
        }

        [CategoryAttribute("Properties"), DescriptionAttribute("Description"), RefreshProperties(RefreshProperties.None), TypeConverter(typeof(ResourceExpandableObjectConverter))]
        public ResourceStringContainer Description
        {
            get;
            set;
        }

        [CategoryAttribute("Properties"), DescriptionAttribute("Base type"), RefreshProperties(RefreshProperties.None)]
        public int BaseType
        {
            get;
            set;
        }

        private int _type;
        [CategoryAttribute("Properties"), DescriptionAttribute("List type"), RefreshProperties(RefreshProperties.None)]
        public int Type
        {
            get
            {
                return _type;
            }
            set
            {
                _type = value;

                string key = "ListTemplate_" + _type.ToString();
                if (key != this.ElementInfo.Key)
                {
                    this.ElementInfo.Manager.RemoveClassesInfoByKey(this.ElementInfo.Key);
                    this.ElementInfo.Key = key;
                }
            }
        }

        [CategoryAttribute("Properties"), DescriptionAttribute("Security bits"), RefreshProperties(RefreshProperties.None)]
        public int SecurityBits
        {
            get;
            set;
        }

        [CategoryAttribute("EventReceivers"), Browsable(true), DisplayName("Attached event receiver classes"), DescriptionAttribute("Classes in project that will automatically generate event receiver registrations for this element."), ReadOnly(false), TypeConverter(typeof(CodeClassCollectionTypeConverter)), Editor(typeof(EventClassCollectionEditor), typeof(UITypeEditor))]
        public List<CodeClass> EventReceiverClasses
        {
            get;
            set;
        }

        [CategoryAttribute("EventReceivers"), Browsable(true), DisplayName("Event registrations"), DescriptionAttribute("Event registrations"), ReadOnly(false), TypeConverter(typeof(EventReceiverCollectionTypeConverter)), Editor(typeof(EventReceiverCollectionEditor), typeof(UITypeEditor))]
        public List<EventReceiverInfo> EventRegistrations
        {
            get;
            set;
        }

        /*
        [CategoryAttribute("Properties"), DescriptionAttribute("On quick launch"), RefreshProperties(RefreshProperties.None)]
        public bool? OnQuickLaunch
        {
            get;
            set;
        }
        */

        /*
        [CategoryAttribute("Properties"), DescriptionAttribute("Sequence"), RefreshProperties(RefreshProperties.None)]
        public string Sequence
        {
            get;
            set;
        }
        */

        public void SetNewSheetFlag(bool IsNewSheet)
        {
            PropertyDescriptor descriptor = TypeDescriptor.GetProperties(this.GetType())["OriginalType"];
            BrowsableAttribute attrib = (BrowsableAttribute)descriptor.Attributes[typeof(BrowsableAttribute)];
            FieldInfo isBrowsable = attrib.GetType().GetField("browsable", BindingFlags.NonPublic | BindingFlags.Instance);
            isBrowsable.SetValue(attrib, IsNewSheet);

            descriptor = TypeDescriptor.GetProperties(this.GetType())["ElementFileName"];
            attrib = (BrowsableAttribute)descriptor.Attributes[typeof(BrowsableAttribute)];
            isBrowsable = attrib.GetType().GetField("browsable", BindingFlags.NonPublic | BindingFlags.Instance);
            isBrowsable.SetValue(attrib, IsNewSheet);
        }

        public BaseTypeInfoStruct FindOriginalTypeByTypeName(string DisplayName)
        {
            OriginalTypeExpandableConverter obj = new OriginalTypeExpandableConverter();

            ICollection coll = obj.GetStandardValues();

            foreach (BaseTypeInfoStruct info in coll)
            {
                if (string.Compare(info.DisplayName, DisplayName, true) == 0)
                    return info;
            }

            return new BaseTypeInfoStruct();
        }

        public override string ToString()
        {
            string s = this.Name;
            if (string.IsNullOrEmpty(s))
                s = this.ElementInfo.ElementName + this.ElementInfo.ID.ToString();

            return "<ListTemplate> " + s;
        }

        [Browsable(false)]
        public override XmlElement PropXmlNode
        {
            get
            {
                XmlElement xel = base.PropXmlNode;

                xel.SetAttribute("SecurityBits", (this.SecurityBits == 0) ? "11" : this.SecurityBits.ToString());

                return xel;
            }
            set
            {
                XmlElement xel = value;

                base.PropXmlNode = xel;
            }
        }

        public class OriginalTypeExpandableConverter : ExpandableObjectConverter
        {
            private List<BaseTypeInfoStruct> m_base_type_list = new List<BaseTypeInfoStruct>();

            public OriginalTypeExpandableConverter()
            {
                //TODO: Copy files from server location
                //string sp_install_path = @"12\TEMPLATE\FEATURES";

                m_base_type_list.Add(new BaseTypeInfoStruct("GenericList", 0, 100, "Generic list", @"\CustomList\CustList"));
                m_base_type_list.Add(new BaseTypeInfoStruct("DocumentLibrary", 1, 101, "Document library", @"\DocumentLibrary\DocLib"));
                m_base_type_list.Add(new BaseTypeInfoStruct("Survey", 4, 102, "Survey", @"\SurveysList\Survey"));
                m_base_type_list.Add(new BaseTypeInfoStruct("Links", 0, 103, "Links", @"\LinksList\Links"));
                m_base_type_list.Add(new BaseTypeInfoStruct("Announcements", 0, 104, "Announcements", @"\AnnouncementsList\Announce"));
                m_base_type_list.Add(new BaseTypeInfoStruct("Contacts", 0, 105, "Contacts", @"\ContactsList\Contacts"));
                m_base_type_list.Add(new BaseTypeInfoStruct("Events", 0, 106, "Events", @"\EventsList\Events"));
                m_base_type_list.Add(new BaseTypeInfoStruct("Tasks", 0, 107, "Tasks", @"\TasksList\Tasks"));
                m_base_type_list.Add(new BaseTypeInfoStruct("DiscussionBoard", 0, 108, "Discussion board", @"\DiscussionsList\Discuss"));
                m_base_type_list.Add(new BaseTypeInfoStruct("PictureLibrary", 1, 109, "Picture library", @"\PictureLibrary\PicLib"));
                m_base_type_list.Add(new BaseTypeInfoStruct("WebPageLibrary", 1, 119, "Web page library", @"\WebPageLibrary\WebPageLib"));
                m_base_type_list.Add(new BaseTypeInfoStruct("CustomGrid", 0, 120, "Custom grid", @"\GridList\GridList"));
                m_base_type_list.Add(new BaseTypeInfoStruct("GanttTasks", 0, 150, "Gantt tasks", @"\GanttTasksList\Gantt"));
                m_base_type_list.Add(new BaseTypeInfoStruct("IssueTracking", 5, 1100, "Issue tracking", @"\IssuesList\Issue"));
                m_base_type_list.Add(new BaseTypeInfoStruct("XMLForm", 1, 115, "XML Form library", @"\XmlFormLibrary\XmlForm"));

            }

            public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
            {
                return true;
            }

            public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
            {
                return true;
            }

            public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
            {
                //StandardValuesCollection coll = new StandardValuesCollection(Enum.GetNames(typeof(PredefinedListTypeEnum)));
                return new StandardValuesCollection(m_base_type_list);
            }

            public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
            {
                return true;
            }

            public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
            {
                return true;
            }
            public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
            {
                if (value is string)
                {
                    BaseTypeInfoStruct info = m_base_type_list.Find(delegate(BaseTypeInfoStruct b) { return b.TemplateName == (value as string); });
                    return info;
                }
                else
                {
                    return base.ConvertFrom(context, culture, value);
                }
            }

            public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
            {
                if (value is BaseTypeInfoStruct && destinationType == typeof(string))
                {
                    if (context != null)
                        context.GetType().GetProperty("Expanded").SetValue(context, true, null);

                    BaseTypeInfoStruct info = (BaseTypeInfoStruct)value;
                    if (info.TemplateName == null)
                        return string.Empty;
                    else
                        return info.TemplateName;
                }
                else
                {
                    return base.ConvertTo(context, culture, value, destinationType);
                }
            }

            public override bool GetPropertiesSupported(ITypeDescriptorContext context)
            {
                return false;
            }
        }

    }

}
